export class Node {
  constructor(ele) {
    this.ele = ele;
    this.next = null;
  }
}

export class LinkedList {
  constructor() {
    this.head = null;
    this.length = 0;
  }

  // 1. 索引方法
  // 1.1 返回链表中特定位置的元素。如果链表中不存在这样的元素，则返回undefined
  getElement(position) {
    if (position >= 0 && position < this.length) {
      let current = this.head;
      // 从链表头部开始查找，直到找到
      for (let i = 0; i < position; i++) {
        current = current.next;
      }
      return current;
    }
    return undefined;
  }
  // 1.2 返回元素在链表中的索引。如果链表中没有该元素则返回-1
  getIndex(element) {
    if (element == undefined) return -1;
    let current = this.head;
    // 从链表头部开始查找，直到找到
    for (let i = 0; i < this.length; i++) {
      if (current.ele === element) {
        return i;
      }
      current = current.next;
    }
    return -1;
  }

  // 2. 插入元素
  // 2.1 在链表尾部插入元素
  push(element) {
    const node = new Node(element);

    if (this.isEmpty()) {
      this.head = node;
    } else {
      let current = this.head;
      for (let i = 0; i < this.length - 1; i++) {
        current = current.next;
      }
      current.next = node;
    }

    this.length++;
    return true;
  }
  // 2.2 在链表特定位置插入元素
  insert(element, position) {
    if (element == undefined) return false;

    if (position >= 0 && position <= this.length) {
      const node = new Node(element);
      let current = this.head;
      if (position === 0) {
        this.head = node;
        node.next = current;
      } else if (position === this.length) {
        return this.push(element);
      } else {
        const prev = this.getElement(position - 1);
        const later = prev.next;
        prev.next = node;
        node.next = later;
      }
      this.length++;
      return true;
    }

    return false;
  }

  // 3. 移除元素
  // 3.1 移除某个元素
  remove(element) {
    const index = this.getIndex(element);
    return this.removeAt(index);
  }
  // 3.2 移除特定位置的元素
  removeAt(position) {
    if (position >= 0 && position < this.length) {
      let current = this.head;
      if (position === 0) {
        this.head = current.next;
      } else {
        const prev = this.getElement(position - 1);
        current = prev.next;
        const later = current.next;
        prev.next = later;
      }
      this.length--;
      return true;
    }
    return false;
  }

  // 4. 其它
  getSize() {
    return this.length;
  }
  isEmpty() {
    return this.getSize() === 0;
  }
}